package 实现阻塞队列;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author zz
 * @Date 2022/7/4
 */
public class BlockQueueDemo {
    public static void main(String[] args) {
        BlockQueue<Integer> queue = new BlockQueue<Integer>(4);
        //queue.push(5);

        new Thread(() -> {
            try{
                System.out.println("添加");
                queue.push(11);
                queue.push(12);
                queue.push(13);
                queue.push(14);
            }catch (Exception e){
                e.printStackTrace();
            }

        }).start();
        new Thread(() -> {
            try {
                System.out.println("取出");
                queue.get();
                //Thread.sleep(1);
                queue.get();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }

    static class BlockQueue<T>{
        private Object queue[];
        private int maxSize;
        private int front;
        private int rear;
        private Lock lock=new ReentrantLock();
        Condition full=lock.newCondition();
        Condition empty=lock.newCondition();

        public BlockQueue(int maxSize){
            this.maxSize=maxSize;
            this.rear=0;
            this.front=0;
            this.queue=new Object[maxSize];
        }

        /**
         *
         * Condition介绍
         *
         *
         * 调用Condition的await()和signal()方法，都必须在lock保护之内，就是说必须在lock.lock()和lock.unlock之间才可以使用
         */

        /**
         * 阻塞入队
         * @param element
         */
        public void push(T element){
            lock.lock();
            try {
                while ((rear+1)%maxSize==front){
                    //System.out.println(element+"入队");
                    System.out.println("队列已满");
                    full.await();
                }
                queue[rear]=element;
                rear=(rear+1)%maxSize;
                empty.signal();
                System.out.println(element+"入队");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }

        public void get(){
            lock.lock();
            try {
                while (rear==front){
                    System.out.println("队列已空");
                    empty.await();
                }
                System.out.println(queue[front]+"出队");
                queue[front]=null;
                front=(front+1)%maxSize;
                full.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
    }
}


